﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

using Job.Core;
using Job.Core.Collections;
using Job.Core.Common;
using Job.Core.Security.Permissions;

namespace Job.Core.Module
{
    /// <summary>
    /// 提供业务逻辑抽像实现，所有业务逻辑类应该继承于此类。
    /// </summary>
    /// <typeparam name="TYPE">类型。</typeparam>
    /// <typeparam name="KEY">唯一标识类型。</typeparam>
    [Serializable]
    public abstract class Business<TKey, TModel> : IDichotomyNode, ICloneable
        where TModel : Business<TKey, TModel>, new()
        where TKey : IComparable
    {
        /// <summary>
        /// 
        /// </summary>
        public Business()
        {
            HasIdentityPK = true;
            PrimaryKey = "ID";
        }

        #region Properties

        /// <summary>
        /// 唯一标识。
        /// </summary>
        public TKey KeyId { get; set; }

        IComparable IDichotomyNode.KeyId
        {
            get { return KeyId; }
        }

        private DataBaseEnum _DataBaseName;

        /// <summary>
        /// 数据库连接名称
        /// </summary>
        public DataBaseEnum DataBaseName
        {
            get { return _DataBaseName; }
            set { _DataBaseName = value; }
        }

        private bool _HasIdentityPK = true;
        private string _PrimaryKey = "";

        /// <summary>
        /// 主键是否自增长字段
        /// </summary>
        public bool HasIdentityPK
        {
            get { return _HasIdentityPK; }
            set { _HasIdentityPK = value; }
        }

        /// <summary>
        /// 主键字段
        /// </summary>
        public string PrimaryKey
        {
            get { return _PrimaryKey; }
            set { _PrimaryKey = value; }
        }

        private static readonly TModel loader = new TModel();

        #endregion

        #region Cache 使用缓存需要 设置 KeyId 且 不能有重复的编号

        private static DichotomyList<TModel> roleCache;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isCache"></param>
        /// <returns></returns>
        public static DichotomyList<TModel> Load(bool isCache)
        {
            if (isCache)
            {
                if (roleCache == null)
                    roleCache = DichotomyList<TModel>.Synchronized(new DichotomyList<TModel>(Opreation().GetList()));
                return roleCache;
            }
            else
            {
                return DichotomyList<TModel>.Synchronized(new DichotomyList<TModel>(Opreation().GetList()));
            }
        }
        public static void ReLoad()
        {
            roleCache = null;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="keyId"></param>
        /// <returns></returns>
        public static TModel GetModelByLoad(TKey keyId)
        {
            TModel T = null;
            if (Load(true).List != null)
                T = Load(true).List.FirstOrDefault(item => item.KeyId.Equals(keyId));
            if (T == null)
                T = new TModel();
            return T;
        }
        #endregion      

        #region Methods
        private static TModel _t = null;
        private static PropertyInfo[] _pis = null;
        /// <summary>
        /// Model层变量Ｔ的实例
        /// </summary>
        public static TModel SModel
        {
            get
            {
                if (_t == null)
                    _t = new TModel();
                return _t;
            }
        }
        /// <summary>
        /// PropertyInfo类：发现属性 (Property) 的属性 (Attribute) 并提供对属性 (Property) 元数据的访问。
        /// </summary>
        /// <returns></returns>
        public virtual PropertyInfo[] GetPropertyInfo()
        {
            if (_pis == null)
            {
                _pis = SModel.GetType().GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public);
            }
            return _pis;
        }


        /// <summary>
        /// 对象数据操作方法
        /// </summary>
        /// <returns></returns>
        public static BaseInstanceDAL<TKey, TModel> Opreation()
        {
            return BaseInstanceDAL<TKey, TModel>.Instance();
        }

        /// <summary>
        /// 根据 id 加载实例。
        /// </summary>
        /// <param name="id">id。</param>
        /// <returns>返回指定 id 的实例，如果不存在可能返回 null。</returns>
        public static TModel Load(TKey id)
        {
            return loader.DataLoad(id);
        }

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="Query"></param>
        /// <returns></returns>
        public static SearchResult<TModel> Search(SearchQuery Query)
        {
            return loader.DataSearch(Query);
        }

        /// <summary>
        /// 创建。
        /// </summary>
        /// <returns>创建成功返回 true，否则返回 false。当创建失败时，可考虑使用 BrokenRules 属性获取失败的原因。</returns>
        public virtual bool Create()
        {
            return Save(DataAction.Create);
        }

        /// <summary>
        /// 更新。
        /// </summary>
        /// <returns>更新成功返回 true，否则返回 false。当更新失败时，可考虑使用 BrokenRules 属性获取失败的原因。</returns>
        public virtual bool Update()
        {
            return Save(DataAction.Update);
        }

        /// <summary>
        /// 删除。
        /// </summary>
        /// <returns>删除成功返回 true，否则返回 false。当删除失败时，可考虑使用 BrokenRules 属性获取失败的原因。</returns>
        public virtual bool Delete()
        {
            return Save(DataAction.Delete);
        }

        /// <summary>
        /// 将对象存储至持久化设备。
        /// </summary>
        /// <param name="action">数据操作类型。</param>
        /// <returns>执行成功返回 true，否则返回 false。当执行失败时，可考虑使用 BrokenRules 属性获取失败的原因。</returns>
        protected virtual bool Save(DataAction action)
        {
            //业务规则验证。
            ValidationRules(action);

            if (!IsValid) return false;

            bool result = false;

            switch (action)
            {
                case DataAction.Create:
                    result = DataCreate();                    
                    break;

                case DataAction.Update:
                    result = DataUpdate();
                    break;

                case DataAction.Delete:
                    result = DataDelete();
                    break;
            }

            if (result)
                OnDataActioned(this, action);

            return result;
        }


        /// <summary>
        /// 从持久设备中加载实例。
        /// </summary>
        /// <param name="id">id。</param>
        /// <returns>返回指定 id 的实例，如果不存在可能返回 null。</returns>
        protected abstract TModel DataLoad(TKey id);

        /// <summary>
        /// 从持久设备中更新对象。
        /// </summary>
        /// <returns>更新成功返回 true，否则返回 false。</returns>
        protected abstract bool DataUpdate();

        /// <summary>
        /// 添加实例到持久设备中。
        /// </summary>
        /// <returns>添加成功返回 true，否则返回 false。</returns>
        protected abstract bool DataCreate();

        /// <summary>
        /// 从持久设备中删除对象。
        /// </summary>
        /// <returns>删除成功返回 true，否则返回 false。</returns>
        protected abstract bool DataDelete();

        /// <summary>
        /// 从持久设备中获取。
        /// </summary>
        /// <returns>返回的实例，如果不存在可能返回 null。</returns>
        protected abstract SearchResult<TModel> DataSearch(SearchQuery Query);

        #endregion

        #region Validation

        private List<RuleViolation> brokenRules = new List<RuleViolation>();

        /// <summary>
        /// 非法的业务规则信息。
        /// 当执行 Create(), Update(), Delete() 失败时可考虑使用此属性获取违反业务规则的信息。
        /// </summary>
        public List<RuleViolation> BrokenRules
        {
            get { return brokenRules; }
        }

        /// <summary>
        /// 指示当前业务实例是否符合业务规则。
        /// </summary>
        public bool IsValid
        {
            get
            {
                return BrokenRules.Count == 0;
            }
        }

        /// <summary>
        /// 添加业务规则。
        /// </summary>       
        /// <param name="isBroken">验证是否为一个无效的规则。</param>
        /// <param name="errorMessage">当规则无效时的信息实例。</param>
        protected void AddRule(bool isBroken, RuleViolation violation)
        {
            if (isBroken)
                BrokenRules.Add(violation);
        }

        /// <summary>
        /// 业务验证，可在派生类中重写，使用AddRule方法添加相应规则。
        /// 注意：重写中必需先调用base.ValidationRules(action)。
        /// </summary>
        protected virtual void ValidationRules(DataAction action)
        {
            BrokenRules.Clear();    //验证前清空。
        }        

        #endregion

        #region Event

        /// <summary>
        /// 完成持久化交互操作后引发的事件。
        /// </summary>
        public static event EventHandler<ActionEventArgs> DataActioned;

        /// <summary>
        /// 完成执久化交互操作后调用的方法。
        /// </summary>
        /// <param name="obj">完成持久化交互操作的实例。</param>
        /// <param name="action">持久化操作类型。</param>
        protected static void OnDataActioned(Business<TKey, TModel> obj, DataAction action)
        {
            if (DataActioned != null)
                DataActioned(obj, new ActionEventArgs(action));
        }

        #endregion

        #region ICloneable 成员

        /// <summary>
        /// 深克隆当前实例。
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            return ObjectFactory.Clone(this);
        }

        #endregion

        #region Overrides

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;

            if (obj.GetType() == this.GetType())
                return obj.GetHashCode() == this.GetHashCode();

            return false;
        }

        public override int GetHashCode()
        {
            return KeyId == null ? base.GetHashCode() : KeyId.GetHashCode();
        }

        #endregion
    }

    #region ActionEventArgs

    /// <summary>
    /// 实体完成相关操作时引发的事件参数。
    /// </summary>
    public class ActionEventArgs : EventArgs
    {
        public DataAction Action;

        public ActionEventArgs(DataAction action)
        {
            Action = action;
        }
    }

    #endregion
}